package com.example.springbootshiro.shiro.config;

import com.example.springbootshiro.shiro.filter.MyAuthenticatingFilter;
import com.example.springbootshiro.shiro.realm.CustomRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by YangGang on 2021/12/14 18:11。
 */
@Configuration
public class ShiroConfig {

    //创建过滤器 ShiroFilter
    @Lazy
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        // 创建并设置我们自定义的过滤器
        Map<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("MyAuthenticatingFilter", new MyAuthenticatingFilter());
        factoryBean.setFilters(filterMap);
        // 配置安全管理器
        factoryBean.setSecurityManager(defaultWebSecurityManager);
        // 设置无权限时跳转的 url;
        factoryBean.setUnauthorizedUrl("/login/unauthorized");

        Map<String, String> filterRuleMap = new HashMap<>();
        // 所有请求通过我们自己的Filter
        filterRuleMap.put("/**", "MyAuthenticatingFilter");
        // 放行不需要权限认证的接口
        filterRuleMap.put("/v2/api-docs", "anon");
        filterRuleMap.put("/swagger-resources/configuration/ui", "anon");
        filterRuleMap.put("/swagger-resources", "anon");
        filterRuleMap.put("/swagger-resources/configuration/security", "anon");
        filterRuleMap.put("/swagger-ui.html", "anon");
        filterRuleMap.put("/webjars/**", "anon");
        //放行登录接口和其他不需要权限的接口
        filterRuleMap.put("/login/**", "anon");
        filterRuleMap.put("/shiro/cache/**", "anon");

        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }


    //创建安全管理器 SecurityManager
    @Bean
    @Lazy
    public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //设置自定义 realm
        defaultWebSecurityManager.setRealm(realm);
        //关闭shiro自带的session
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        defaultWebSecurityManager.setSubjectDAO(subjectDAO);
        return defaultWebSecurityManager;
    }

    //创建 realm
    @Lazy
    @Bean(name = "realm")
    public Realm getRealm() {
        CustomRealm customRealm = new CustomRealm();
        //加密凭证器
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashIterations(1024);//散列次数
        matcher.setHashAlgorithmName("md5");//MD5的方式
        customRealm.setCredentialsMatcher(matcher);
        //开启缓存管理器
        customRealm.setCacheManager(new EhCacheManager());
        customRealm.setCachingEnabled(true);//开启全局缓存
        customRealm.setAuthenticationCachingEnabled(true);//开启认证的缓存
        customRealm.setAuthenticationCacheName("authenticationCache");//名称
        customRealm.setAuthorizationCachingEnabled(true);//开启授权的缓存
        customRealm.setAuthorizationCacheName("authorizationCache");
        return customRealm;
    }


}
